package com.scau402.system1.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.scau402.common.exception.ServiceException;
import com.scau402.common.utils.SecurityUtils;
import com.scau402.common.utils.StringUtils;
import com.scau402.system.domain.WmsInboundOrder;
import com.scau402.system1.mapper.WmsWarehouseStorageMapper;
import com.scau402.system1.domain.dto.WmsWarehouseDTO;
import com.scau402.system1.domain.dto.WmsWarehouseStorageDTO;
import com.scau402.system1.domain.po.WmsWarehouseDO;
import com.scau402.system1.domain.po.WmsWarehouseStoragePO;
import com.scau402.system1.domain.vo.WmsStorageVO;
import com.scau402.system1.domain.vo.WmsWarehouseStorageVO;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 仓库仓位Service接口
 *
 * @author ruoyi
 * @date 2023-06-26
 */
@Service
public class WmsWarehouseStorageService {

    @Resource
    private WmsWarehouseStorageMapper wmsWarehouseStorageMapper;

    @Resource
    private WmsWarehouseService wmsWarehouseService;

    /**
     * 查询仓库仓位
     *
     * @param id 仓库仓位主键
     * @return 仓库仓位
     */
    public WmsWarehouseStoragePO selectWmsWarehouseStorageById(Long id) {
        return wmsWarehouseStorageMapper.selectOne(
                new LambdaQueryWrapper<WmsWarehouseStoragePO>()
                        .eq(WmsWarehouseStoragePO::getId, id)
                        .eq(WmsWarehouseStoragePO::getDelFlag, "0")
        );
    }

    /**
     * 查询仓库仓位列表
     */
    public List<WmsStorageVO> list(WmsWarehouseStorageDTO wmsWarehouseStorageDTO) {
        return wmsWarehouseStorageMapper.selectJoinList(
                WmsStorageVO.class,
                new MPJLambdaWrapper<WmsWarehouseStoragePO>()
                        .selectAll(WmsWarehouseStoragePO.class)
                        .selectAs(WmsWarehouseDO::getWarehouseName, WmsStorageVO::getParentWarehouseName)
                        .selectAs(WmsWarehouseDO::getWarehouseCode, WmsStorageVO::getParentWarehouseCode)
                        .selectAs(WmsWarehouseDO::getStatus, WmsStorageVO::getStatus)
                        .leftJoin(WmsWarehouseDO.class, WmsWarehouseDO::getId, WmsWarehouseStoragePO::getParentWarehouse)
                        .eq(WmsWarehouseStoragePO::getDelFlag, "0")
                        .like(
                                StringUtils.isNotEmpty(wmsWarehouseStorageDTO.getStorageCode()),
                                WmsWarehouseStoragePO::getStorageCode,
                                wmsWarehouseStorageDTO.getStorageCode()
                        )
                        .like(
                                StringUtils.isNotEmpty(wmsWarehouseStorageDTO.getStorageName()),
                                WmsWarehouseStoragePO::getStorageName,
                                wmsWarehouseStorageDTO.getStorageName()
                        )
                        .eq(WmsWarehouseDO::getDelFlag, "0")
                        .eq(
                                StringUtils.isNotEmpty(wmsWarehouseStorageDTO.getParentWarehouse()),
                                WmsWarehouseDO::getId,
                                wmsWarehouseStorageDTO.getParentWarehouse()
                        )
                        .eq(
                                StringUtils.isNotEmpty(wmsWarehouseStorageDTO.getStatus()),
                                WmsWarehouseDO::getStatus,
                                wmsWarehouseStorageDTO.getStatus()
                        )
                        .orderByDesc(WmsWarehouseStoragePO::getCreateTime)

        );
    }

    /**
     * 新增仓库仓位
     *
     * @param wmsWarehouseStoragePO 仓库仓位
     */
    public void insertWmsWarehouseStorage(WmsWarehouseStoragePO wmsWarehouseStoragePO) {
        // 编码是否为以WS开头任意数字的组合
        String regex = "WS\\d+";
        boolean matcher = Pattern.matches(regex, wmsWarehouseStoragePO.getStorageCode());
        if (!matcher) {
            throw new ServiceException("编码应以字母WS开头");
        }

        // 编码是否重复
        WmsWarehouseStoragePO one = wmsWarehouseStorageMapper.selectOne(
                new LambdaQueryWrapper<WmsWarehouseStoragePO>()
                        .eq(WmsWarehouseStoragePO::getStorageCode, wmsWarehouseStoragePO.getStorageCode())
                        .eq(WmsWarehouseStoragePO::getTenantId, SecurityUtils.getLoginUser().getTenantId())
                        .eq(WmsWarehouseStoragePO::getDelFlag, "0")
        );

        if (one != null) {
            throw new ServiceException("仓位编码已存在");
        }

        // 检查仓位名称是否已经存在
        one = wmsWarehouseStorageMapper.selectOne(
                new LambdaQueryWrapper<WmsWarehouseStoragePO>()
                        .eq(WmsWarehouseStoragePO::getStorageName, wmsWarehouseStoragePO.getStorageName())
                        .eq(WmsWarehouseStoragePO::getTenantId, SecurityUtils.getLoginUser().getTenantId())
                        .eq(WmsWarehouseStoragePO::getParentWarehouse, wmsWarehouseStoragePO.getParentWarehouse())
                        .eq(WmsWarehouseStoragePO::getDelFlag, "0")
        );
        if (one != null) {
            throw new ServiceException("仓位名称已存在");
        }

        wmsWarehouseStoragePO.setId(null);
        if (wmsWarehouseStoragePO.getMaxCap() == null) {
            wmsWarehouseStoragePO.setMaxCap(-1L);
        }
        wmsWarehouseStoragePO.setUsedCap(0L);
        wmsWarehouseStoragePO.setDelFlag("0");

        wmsWarehouseStoragePO.setTenantId(SecurityUtils.getLoginUser().getTenantId());

        wmsWarehouseStoragePO.setCreateBy(SecurityUtils.getLoginUser().getUsername());
        wmsWarehouseStoragePO.setCreateTime(new Date());

        wmsWarehouseStoragePO.setUpdateBy(SecurityUtils.getLoginUser().getUsername());
        wmsWarehouseStoragePO.setUpdateTime(new Date());

        wmsWarehouseService.increaseUsedCap(wmsWarehouseStoragePO.getParentWarehouse(), wmsWarehouseStoragePO.getMaxCap());
        doIfSetDefault(wmsWarehouseStoragePO);
        wmsWarehouseStorageMapper.insert(wmsWarehouseStoragePO);
    }

    private void doIfSetDefault(WmsWarehouseStoragePO wmsWarehouseStoragePO) {
        if ("1".equals(wmsWarehouseStoragePO.getIsDefault())) {
            wmsWarehouseStorageMapper.update(
                    null,
                    new LambdaUpdateWrapper<WmsWarehouseStoragePO>()
                            .eq(WmsWarehouseStoragePO::getParentWarehouse, wmsWarehouseStoragePO.getParentWarehouse())
                            .eq(WmsWarehouseStoragePO::getTenantId, SecurityUtils.getLoginUser().getTenantId())
                            .eq(WmsWarehouseStoragePO::getParentWarehouse, wmsWarehouseStoragePO.getParentWarehouse())
                            .eq(WmsWarehouseStoragePO::getDelFlag, "0")
                            .set(WmsWarehouseStoragePO::getIsDefault, "0")
            );
        }
    }

    /**
     * 修改仓库仓位
     *
     * @param wmsWarehouseStoragePO 仓库仓位
     */
    public void updateWmsWarehouseStorage(WmsWarehouseStoragePO wmsWarehouseStoragePO) {
        if (wmsWarehouseStoragePO.getMaxCap() == null) {
            wmsWarehouseStoragePO.setMaxCap(-1L);
        }
        WmsWarehouseStoragePO origin = selectWmsWarehouseStorageById(wmsWarehouseStoragePO.getId());
        if (!Objects.equals(origin.getMaxCap(), wmsWarehouseStoragePO.getMaxCap())) {
            if (Objects.equals(wmsWarehouseStoragePO.getMaxCap(), -1L) || origin.getMaxCap() < wmsWarehouseStoragePO.getMaxCap()) {
                wmsWarehouseService.increaseUsedCap(
                        wmsWarehouseStoragePO.getParentWarehouse(),
                        wmsWarehouseStoragePO.getMaxCap() - origin.getMaxCap()
                );
            } else {
                wmsWarehouseService.decreaseUsedCap(
                        wmsWarehouseStoragePO.getParentWarehouse(),
                        origin.getMaxCap() - wmsWarehouseStoragePO.getMaxCap()
                );
            }

            if (origin.getUsedCap() > wmsWarehouseStoragePO.getMaxCap()) {
                throw new ServiceException("当前设置的最大容量小于已使用的容量");
            }
        }

        doIfSetDefault(wmsWarehouseStoragePO);
        wmsWarehouseStorageMapper.update(
                wmsWarehouseStoragePO,
                new LambdaUpdateWrapper<WmsWarehouseStoragePO>()
                        .eq(WmsWarehouseStoragePO::getId, wmsWarehouseStoragePO.getId())
                        .eq(WmsWarehouseStoragePO::getTenantId, SecurityUtils.getLoginUser().getTenantId())
        );
    }

    /**
     * 批量删除仓库仓位
     *
     * @param ids 需要删除的仓库仓位主键集合
     */
    public void deleteWmsWarehouseStorageByIds(Long[] ids) {
        for (Long id : ids) {
            WmsWarehouseStoragePO wmsWarehouseStoragePO = selectWmsWarehouseStorageById(id);
            if (0 < wmsWarehouseStoragePO.getUsedCap()) {
                throw new ServiceException("当前仓位还存有货物，无法删除");
            }
            if (!Objects.equals(wmsWarehouseStoragePO.getMaxCap(), -1L)) {
                wmsWarehouseService.decreaseUsedCap(
                        wmsWarehouseStoragePO.getParentWarehouse(),
                        wmsWarehouseStoragePO.getMaxCap()
                );
            }
            wmsWarehouseStorageMapper.update(
                    null,
                    new LambdaUpdateWrapper<WmsWarehouseStoragePO>()
                            .eq(WmsWarehouseStoragePO::getId, id)
                            .set(WmsWarehouseStoragePO::getDelFlag, "2")
            );

        }
    }

    public boolean checkFull(Long id) {
        WmsWarehouseStoragePO wmsWarehouseStoragePO = this.selectWmsWarehouseStorageById(id);
        if (wmsWarehouseStoragePO.getMaxCap() == -1) {
            return false;
        }

        return wmsWarehouseStoragePO.getUsedCap() >= wmsWarehouseStoragePO.getMaxCap();
    }

    public void updateQuantity(WmsInboundOrder wmsInboundOrder) {
        WmsWarehouseStoragePO storage = selectWmsWarehouseStorageById(wmsInboundOrder.getDesStorageId());
        if (storage.getMaxCap() != -1) {
            if (storage.getMaxCap() < storage.getUsedCap() + wmsInboundOrder.getTotalQuantity()) {
                throw new ServiceException("仓位容量不足");
            }
        }
        wmsWarehouseStorageMapper.update(
                null,
                new LambdaUpdateWrapper<WmsWarehouseStoragePO>()
                        .eq(WmsWarehouseStoragePO::getId, wmsInboundOrder.getDesStorageId())
                        .set(WmsWarehouseStoragePO::getUsedCap, storage.getUsedCap() + wmsInboundOrder.getTotalQuantity())
        );
    }

    public List<WmsWarehouseStorageVO> listAll() {
        List<WmsWarehouseDO> wmsWarehouseDOS = wmsWarehouseService.list(new WmsWarehouseDTO());
        return wmsWarehouseDOS.stream().map(item -> {
            WmsWarehouseStorageVO wmsWarehouseStorageVO = new WmsWarehouseStorageVO();
            wmsWarehouseStorageVO.setWarehouseId(item.getId());
            wmsWarehouseStorageVO.setWarehouseName(item.getWarehouseName());
            wmsWarehouseStorageVO.setWarehouseCode(item.getWarehouseCode());
            wmsWarehouseStorageVO.setWarehouseStatus(item.getStatus());
            wmsWarehouseStorageVO.setStorages(new ArrayList<>());
            return wmsWarehouseStorageVO;
        }).peek(item -> {
            List<WmsWarehouseStoragePO> wmsWarehouseStoragePOS = wmsWarehouseStorageMapper.selectList(
                    new LambdaQueryWrapper<WmsWarehouseStoragePO>()
                            .eq(WmsWarehouseStoragePO::getParentWarehouse, item.getWarehouseId())
                            .eq(WmsWarehouseStoragePO::getDelFlag, "0")
                            .eq(WmsWarehouseStoragePO::getTenantId, SecurityUtils.getLoginUser().getTenantId())
            );
            item.setStorages(wmsWarehouseStoragePOS);
        }).collect(Collectors.toList());
    }

    /**
     * tips:这个updateInventory实际是一个 jade_quantity = jade_quantity - jadeQuantity的实现
     * @param storageId
     * @param jadeQuantity
     */
    public void updateInventory(Long storageId, Long jadeQuantity) {
        wmsWarehouseStorageMapper.updateInventory(storageId, jadeQuantity);
    }

    /**
     * 更新库存数量（默认+实现）
     * @param storageId 仓位id
     * @param jadeQuantity 变化的数量
     * @since 2024/2/20
     */
    public void addInventory(Long storageId, Long jadeQuantity) {
        wmsWarehouseStorageMapper.addInventory(storageId, jadeQuantity);
    }

    /**
     * 根据仓位id获取已使用容量和最大容量
     * @param storageId 仓位id
     * @return
     */
    public WmsWarehouseStoragePO selectCapById(Long storageId) {
        return wmsWarehouseStorageMapper.selectCapById(storageId);
    }
}
